package middleware

import (
	"context"
	"time"

	"admin_template/bff/admin/hertz_gen/base"
	conf "admin_template/bff/admin/internal/base/config"
	"admin_template/bff/admin/internal/pkg/utils"

	"github.com/cloudwego/hertz/pkg/app"
	"github.com/cloudwego/hertz/pkg/protocol/consts"
	"github.com/golang-jwt/jwt/v5"
	"github.com/pkg/errors"
)

func JWTAuth(conf *conf.Config) app.HandlerFunc {
	return func(c context.Context, ctx *app.RequestContext) {
		token := ctx.Request.Header.Get("X-Authorization")
		if token == "" {
			reply := base.BaseReply{
				Code: base.ErrCode_ReLogin,
				Msg:  "未设置用户Token",
			}
			utils.Reply(ctx, consts.StatusOK, &reply)
			ctx.Abort()
			return
		}
		j := utils.NewJWT(conf.SystemConfig.Jwt.SigningKey, conf.SystemConfig.Jwt.Issuer, int64(conf.SystemConfig.Jwt.BufferTime), int64(conf.SystemConfig.Jwt.ExpiresTime))
		claims, err := j.ParseToken(token)
		if err != nil {
			if errors.Is(err, jwt.ErrTokenExpired) {
				reply := base.BaseReply{
					Code: base.ErrCode_ReLogin,
					Msg:  "用户Token已过期",
				}
				utils.Reply(ctx, consts.StatusOK, &reply)
				ctx.Abort()
			} else {
				reply := base.BaseReply{
					Code: base.ErrCode_Fail,
					Msg:  err.Error(),
				}
				utils.Reply(ctx, consts.StatusOK, &reply)
				ctx.Abort()
			}
			return
		}
		if claims.ExpiresAt.Unix()-time.Now().Unix() < claims.BufferTime {
			claims.NotBefore = jwt.NewNumericDate(time.Now().Add(-time.Second * 1000))
			claims.IssuedAt = jwt.NewNumericDate(time.Now())
			claims.ExpiresAt = jwt.NewNumericDate(time.Now().Add(time.Second * time.Duration(j.ExpiresTime)))
			newToken, _ := j.CreateTokenByOldToken(token, *claims)
			ctx.Header("X-New-Token", newToken)
		}
		ctx.Set("userToken", claims.BaseClaims)
		ctx.Next(c)
	}
}
